#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
线性代数基础 - AI应用开发必备数学知识
重点：理解形状和基本操作，为机器学习打基础
"""

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号
print("🚀 线性代数基础教学开始")
print("=" * 50)

# 1. 向量基础
print("\n1. 向量基础")
print("-" * 30)

# 创建向量
vector_1d = np.array([1, 2, 3, 4, 5])
vector_2d = np.array([[1], [2], [3]])  # 列向量

print(f"一维向量: {vector_1d}")
print(f"形状: {vector_1d.shape}")
print(f"二维向量:\n{vector_2d}")
print(f"形状: {vector_2d.shape}")

# 向量运算
vector_a = np.array([1, 2, 3])
vector_b = np.array([4, 5, 6])

print(f"\n向量加法: {vector_a} + {vector_b} = {vector_a + vector_b}")
print(f"向量数乘: 2 * {vector_a} = {2 * vector_a}")
print(f"点积: {vector_a} · {vector_b} = {np.dot(vector_a, vector_b)}")

# 2. 矩阵基础
print("\n\n2. 矩阵基础")
print("-" * 30)

# 创建矩阵
matrix_2x3 = np.array([[1, 2, 3], [4, 5, 6]])
matrix_3x2 = np.array([[1, 2], [3, 4], [5, 6]])

print(f"2x3矩阵:\n{matrix_2x3}")
print(f"形状: {matrix_2x3.shape}")
print(f"3x2矩阵:\n{matrix_3x2}")
print(f"形状: {matrix_3x2.shape}")

# 矩阵运算
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

print(f"\n矩阵加法:\n{A} +\n{B} =\n{A + B}")
print(f"矩阵乘法:\n{A} ×\n{B} =\n{np.dot(A, B)}")

# 3. 特殊矩阵
print("\n\n3. 特殊矩阵")
print("-" * 30)

# 单位矩阵
identity_matrix = np.eye(3)
print(f"3x3单位矩阵:\n{identity_matrix}")

# 零矩阵
zero_matrix = np.zeros((2, 3))
print(f"2x3零矩阵:\n{zero_matrix}")

# 全1矩阵
ones_matrix = np.ones((2, 2))
print(f"2x2全1矩阵:\n{ones_matrix}")

# 4. 矩阵转置和形状变换
print("\n\n4. 矩阵转置和形状变换")
print("-" * 30)

matrix = np.array([[1, 2, 3], [4, 5, 6]])
print(f"原矩阵:\n{matrix}")
print(f"转置矩阵:\n{matrix.T}")
print(f"重塑为3x2:\n{matrix.reshape(3, 2)}")

# 5. 在机器学习中的应用示例
print("\n\n5. 机器学习中的应用示例")
print("-" * 30)

# 示例1: 线性回归的矩阵表示
print("示例1: 线性回归的矩阵表示")

# 特征矩阵 X (m个样本，n个特征)
X = np.array([[1, 2], [1, 3], [1, 4], [1, 5]])  # 第一列是偏置项
print(f"特征矩阵 X (4个样本，2个特征):\n{X}")

# 权重向量 w
w = np.array([0.5, 1.2])
print(f"权重向量 w: {w}")

# 预测值 y_hat = X × w
y_hat = np.dot(X, w)
print(f"预测值 y_hat = X × w: {y_hat}")

# 示例2: 神经网络中的权重矩阵
print("\n示例2: 神经网络权重矩阵")

# 输入层到隐藏层的权重矩阵
input_size = 3
hidden_size = 4
W1 = np.random.randn(input_size, hidden_size)
print(f"输入层到隐藏层权重矩阵 W1 ({input_size}x{hidden_size}):\n{W1}")

# 6. 可视化理解
print("\n\n6. 可视化理解")
print("-" * 30)

# 向量可视化
fig =  plt.figure(figsize=(18, 8))

# 子图1: 向量表示
plt.subplot(1, 4, 1)
vectors = np.array([[0, 0, 2, 3], [0, 0, 4, 1],[0, 0, 5, 6]])  # [x1, y1, x2, y2]

# 假如我们只对第一个向量感兴趣，即索引为0的向量
selected_vector = vectors[0].reshape(1, -1)  # 选择并重塑形状以匹配预期输入格式

# 分离出X, Y起始点坐标和dx, dy值
X, Y, U, V = zip(*vectors)


plt.quiver(X, Y, U, V, 
           angles='xy', scale_units='xy', scale=1, color=['r', 'b'])
plt.xlim(-1, max(U) + 1)
plt.ylim(-1, max(V) + 1)
plt.grid(True)
plt.title('向量表示')
plt.xlabel('X轴')
plt.ylabel('Y轴')



# 子图2: 矩阵热力图
plt.subplot(1, 4, 2)
matrix_vis = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
plt.imshow(matrix_vis, cmap='viridis', interpolation='nearest')
plt.colorbar()
plt.title('矩阵热力图')

# 子图3: 矩阵乘法示意
plt.subplot(1, 4, 3)
A_vis = np.array([[1, 2], [3, 4]])
B_vis = np.array([[2, 0], [1, 3]])
result_vis = np.dot(A_vis, B_vis)

plt.text(0.1, 0.8, f'A = {A_vis[0]}\n    {A_vis[1]}', fontsize=10)
plt.text(0.1, 0.6, f'B = {B_vis[0]}\n    {B_vis[1]}', fontsize=10)
plt.text(0.1, 0.4, f'A×B = {result_vis[0]}\n      {result_vis[1]}', fontsize=10)
plt.axis('off')
plt.title('矩阵乘法')


# 子图4: 3D向量可视化
# 调整子图位置，增加边距
ax = fig.add_axes([0.75, 0.1, 0.2, 0.8], projection='3d')

# 创建3D向量数据
vectors_3d = np.array([[0, 0, 0, 2, 3, 4], [0, 0, 0, 4, 5, 6], [0, 0, 0, 7, 8, 9]])  # [x1, y1, z1, x2, y2, z2]
X3, Y3, Z3, U3, V3, W3 = zip(*vectors_3d)

ax.quiver(X3, Y3, Z3, U3, V3, W3, length=1, arrow_length_ratio=0.1, linewidths=2, colors=['r', 'g', 'b'])
ax.set_xlim([min(X3 + U3) - 3, max(X3 + U3) + 3])
ax.set_ylim([min(Y3 + V3) - 3, max(Y3 + V3) + 3])
ax.set_zlim([min(Z3 + W3) - 3, max(Z3 + W3) + 3])
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')
ax.set_title('三个三维向量')

# 调整其他子图的位置，为3D图留出空间
plt.subplots_adjust(right=0.7)  # 为右侧3D图留出空间


plt.tight_layout()
plt.savefig('linear_algebra_visualization.png', dpi=500, bbox_inches='tight')
plt.show()





# 7. 实战练习
print("\n\n7. 实战练习")
print("-" * 30)

print("练习1: 计算两个向量的点积")
vec1 = np.array([1, 3, 5])
vec2 = np.array([2, 4, 6])
print(f"向量1: {vec1}")
print(f"向量2: {vec2}")
print("请计算点积并验证:")
print(f"正确答案: {np.dot(vec1, vec2)}")

print("\n练习2: 矩阵乘法")
M1 = np.array([[1, 2], [3, 4]])
M2 = np.array([[2, 0], [1, 2]])
print(f"矩阵1:\n{M1}")
print(f"矩阵2:\n{M2}")
print("请计算矩阵乘积并验证:")
print(f"正确答案:\n{np.dot(M1, M2)}")

print("\n" + "=" * 50)
print("🎯 学习要点总结:")
print("1. 理解向量的概念和运算")
print("2. 掌握矩阵的基本操作")
print("3. 熟悉矩阵乘法的规则")
print("4. 了解在机器学习中的应用")
print("5. 重点：形状匹配和维度理解")

print("\n💡 下一步学习:")
print("- 概率统计基础")
print("- 微积分概念（梯度、导数）")
print("- 在实际机器学习项目中的应用")